Kuasai React Error Boundaries untuk membangun aplikasi tangguh dan ramah pengguna. Pelajari praktik terbaik, implementasi, dan strategi penanganan error tingkat lanjut.
React Error Boundaries: Teknik Penanganan Kesalahan yang Anggun untuk Aplikasi yang Kuat
Di dunia pengembangan web yang dinamis, membuat aplikasi yang kuat dan ramah pengguna adalah yang terpenting. React, sebuah pustaka JavaScript populer untuk membangun antarmuka pengguna, menyediakan mekanisme yang kuat untuk menangani kesalahan secara anggun: Error Boundaries. Panduan komprehensif ini membahas konsep Error Boundaries, menjelajahi tujuan, implementasi, dan praktik terbaik untuk membangun aplikasi React yang tangguh.
Memahami Kebutuhan akan Error Boundaries
Komponen React, seperti kode pada umumnya, rentan terhadap kesalahan. Kesalahan ini dapat berasal dari berbagai sumber, termasuk:
- Data Tak Terduga: Komponen mungkin menerima data dalam format yang tidak terduga, yang menyebabkan masalah rendering.
- Kesalahan Logika: Bug dalam logika komponen dapat menyebabkan perilaku dan kesalahan yang tidak terduga.
- Dependensi Eksternal: Masalah dengan pustaka eksternal atau API dapat menyebarkan kesalahan ke dalam komponen Anda.
Tanpa penanganan kesalahan yang tepat, kesalahan dalam komponen React dapat merusak seluruh aplikasi, yang mengakibatkan pengalaman pengguna yang buruk. Error Boundaries menyediakan cara untuk menangkap kesalahan ini dan mencegahnya menyebar ke atas pohon komponen, memastikan bahwa aplikasi tetap fungsional bahkan ketika komponen individual gagal.
Apa itu React Error Boundaries?
Error Boundaries adalah komponen React yang menangkap kesalahan JavaScript di mana pun di dalam pohon komponen turunannya, mencatat kesalahan tersebut, dan menampilkan UI fallback alih-alih pohon komponen yang rusak. Mereka bertindak sebagai jaring pengaman, mencegah kesalahan merusak seluruh aplikasi.
Karakteristik utama dari Error Boundaries:
- Hanya Komponen Kelas: Error Boundaries harus diimplementasikan sebagai komponen kelas. Komponen fungsional dan hook tidak dapat digunakan untuk membuat Error Boundaries.
- Metode Lifecycle: Mereka menggunakan metode lifecycle spesifik,
static getDerivedStateFromError()
dancomponentDidCatch()
, untuk menangani kesalahan. - Penanganan Kesalahan Lokal: Error Boundaries hanya menangkap kesalahan di komponen turunannya, bukan di dalam dirinya sendiri.
Mengimplementasikan Error Boundaries
Mari kita ikuti proses pembuatan komponen Error Boundary dasar:
1. Membuat Komponen Error Boundary
Pertama, buat komponen kelas baru, misalnya, bernama ErrorBoundary
:
import React from 'react';
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = {
hasError: false
};
}
static getDerivedStateFromError(error) {
// Perbarui state agar render berikutnya akan menampilkan UI fallback.
return {
hasError: true
};
}
componentDidCatch(error, errorInfo) {
// Anda juga bisa mencatat error ke layanan pelaporan kesalahan
console.error("Caught error: ", error, errorInfo);
// Contoh: logErrorToMyService(error, errorInfo);
}
render() {
if (this.state.hasError) {
// Anda dapat merender UI fallback kustom apa pun
return (
<div>
<h2>Terjadi kesalahan.</h2>
<details style={{ whiteSpace: 'pre-wrap' }}>
{this.state.error && this.state.error.toString()}
<br />
{this.state.errorInfo.componentStack}
</details>
</div>
);
}
return this.props.children;
}
}
export default ErrorBoundary;
Penjelasan:
- Constructor: Menginisialisasi state komponen dengan
hasError: false
. static getDerivedStateFromError(error)
: Metode lifecycle ini dipanggil setelah sebuah kesalahan dilemparkan oleh komponen turunan. Metode ini menerima kesalahan sebagai argumen dan memungkinkan Anda untuk memperbarui state komponen. Di sini, kita mengaturhasError
menjaditrue
untuk memicu UI fallback. Ini adalah metodestatic
, jadi Anda tidak bisa menggunakanthis
di dalam fungsi.componentDidCatch(error, errorInfo)
: Metode lifecycle ini dipanggil setelah sebuah kesalahan dilemparkan oleh komponen turunan. Metode ini menerima dua argumen:error
: Kesalahan yang dilemparkan.errorInfo
: Objek yang berisi informasi tentang tumpukan komponen tempat kesalahan terjadi. Ini sangat berharga untuk debugging.
Dalam metode ini, Anda dapat mencatat kesalahan ke layanan seperti Sentry, Rollbar, atau solusi pencatatan kustom. Hindari mencoba me-render ulang atau memperbaiki kesalahan secara langsung di dalam fungsi ini; tujuan utamanya adalah untuk mencatat masalah.
render()
: Metode render memeriksa statehasError
. Jikatrue
, metode ini merender UI fallback (dalam kasus ini, pesan kesalahan sederhana). Jika tidak, metode ini merender turunan komponen.
2. Menggunakan Error Boundary
Untuk menggunakan Error Boundary, cukup bungkus komponen apa pun yang mungkin menimbulkan kesalahan dengan komponen ErrorBoundary
:
import ErrorBoundary from './ErrorBoundary';
function MyComponent() {
// Komponen ini mungkin menimbulkan kesalahan
return (
<ErrorBoundary>
<PotentiallyBreakingComponent />
</ErrorBoundary>
);
}
export default MyComponent;
Jika PotentiallyBreakingComponent
menimbulkan kesalahan, ErrorBoundary
akan menangkapnya, mencatat kesalahan tersebut, dan merender UI fallback.
3. Contoh Ilustrasi
Pertimbangkan aplikasi e-commerce yang menampilkan informasi produk yang diambil dari server jarak jauh. Sebuah komponen, ProductDisplay
, bertanggung jawab untuk merender detail produk. Namun, server terkadang dapat mengembalikan data yang tidak terduga, yang menyebabkan kesalahan rendering.
// ProductDisplay.js
import React from 'react';
function ProductDisplay({ product }) {
// Simulasikan potensi kesalahan jika product.price bukan angka
if (typeof product.price !== 'number') {
throw new Error('Harga produk tidak valid');
}
return (
<div>
<h2>{product.name}</h2>
<p>Harga: {product.price}</p>
<img src={product.imageUrl} alt={product.name} />
</div>
);
}
export default ProductDisplay;
Untuk melindungi dari kesalahan semacam itu, bungkus komponen ProductDisplay
dengan ErrorBoundary
:
// App.js
import React from 'react';
import ErrorBoundary from './ErrorBoundary';
import ProductDisplay from './ProductDisplay';
function App() {
const product = {
name: 'Produk Contoh',
price: 'Bukan Angka', // Data yang sengaja disalahkan
imageUrl: 'https://example.com/image.jpg'
};
return (
<div>
<ErrorBoundary>
<ProductDisplay product={product} />
</ErrorBoundary>
</div>
);
}
export default App;
Dalam skenario ini, karena product.price
sengaja diatur ke string alih-alih angka, komponen ProductDisplay
akan menimbulkan kesalahan. ErrorBoundary
akan menangkap kesalahan ini, mencegah seluruh aplikasi rusak, dan menampilkan UI fallback alih-alih komponen ProductDisplay
yang rusak.
4. Error Boundaries dalam Aplikasi Internasionalisasi
Saat membangun aplikasi untuk audiens global, pesan kesalahan harus dilokalkan untuk memberikan pengalaman pengguna yang lebih baik. Error Boundaries dapat digunakan bersama dengan pustaka internasionalisasi (i18n) untuk menampilkan pesan kesalahan yang diterjemahkan.
// ErrorBoundary.js (dengan dukungan i18n)
import React from 'react';
import { useTranslation } from 'react-i18next'; // Dengan asumsi Anda menggunakan react-i18next
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = {
hasError: false,
error: null,
errorInfo: null,
};
}
static getDerivedStateFromError(error) {
return {
hasError: true,
error: error,
};
}
componentDidCatch(error, errorInfo) {
console.error("Caught error: ", error, errorInfo);
this.setState({errorInfo: errorInfo});
}
render() {
if (this.state.hasError) {
return (
<FallbackUI error={this.state.error} errorInfo={this.state.errorInfo}/>
);
}
return this.props.children;
}
}
const FallbackUI = ({error, errorInfo}) => {
const { t } = useTranslation();
return (
<div>
<h2>{t('error.title')}</h2>
<p>{t('error.message')}</p>
<details style={{ whiteSpace: 'pre-wrap' }}>
{error && error.toString()}<br />
{errorInfo?.componentStack}
</details>
</div>
);
}
export default ErrorBoundary;
Dalam contoh ini, kita menggunakan react-i18next
untuk menerjemahkan judul dan pesan kesalahan di UI fallback. Fungsi t('error.title')
dan t('error.message')
akan mengambil terjemahan yang sesuai berdasarkan bahasa yang dipilih pengguna.
5. Pertimbangan untuk Server-Side Rendering (SSR)
Saat menggunakan Error Boundaries dalam aplikasi yang di-render di sisi server, sangat penting untuk menangani kesalahan dengan tepat untuk mencegah server rusak. Dokumentasi React merekomendasikan agar Anda menghindari penggunaan Error Boundaries untuk pulih dari kesalahan rendering di server. Sebagai gantinya, tangani kesalahan sebelum merender komponen, atau render halaman kesalahan statis di server.
Praktik Terbaik Menggunakan Error Boundaries
- Bungkus Komponen Granular: Bungkus komponen individual atau bagian kecil aplikasi Anda dengan Error Boundaries. Ini mencegah satu kesalahan merusak seluruh UI. Pertimbangkan untuk membungkus fitur atau modul tertentu daripada seluruh aplikasi.
- Catat Kesalahan: Gunakan metode
componentDidCatch()
untuk mencatat kesalahan ke layanan pemantauan. Ini membantu Anda melacak dan memperbaiki masalah di aplikasi Anda. Layanan seperti Sentry, Rollbar, dan Bugsnag adalah pilihan populer untuk pelacakan dan pelaporan kesalahan. - Sediakan UI Fallback yang Informatif: Tampilkan pesan kesalahan yang ramah pengguna di UI fallback. Hindari jargon teknis dan berikan instruksi tentang cara melanjutkan (misalnya, segarkan halaman, hubungi dukungan). Jika memungkinkan, sarankan tindakan alternatif yang dapat dilakukan pengguna.
- Jangan Gunakan Berlebihan: Hindari membungkus setiap komponen dengan Error Boundary. Fokus pada area di mana kesalahan lebih mungkin terjadi, seperti komponen yang mengambil data dari API eksternal atau menangani interaksi pengguna yang kompleks.
- Uji Error Boundaries: Pastikan Error Boundaries Anda berfungsi dengan benar dengan sengaja menimbulkan kesalahan pada komponen yang dibungkusnya. Tulis pengujian unit atau pengujian integrasi untuk memverifikasi bahwa UI fallback ditampilkan seperti yang diharapkan dan kesalahan dicatat dengan benar.
- Error Boundaries BUKAN untuk:
- Penangan event (event handler)
- Kode asinkron (misalnya, callback
setTimeout
ataurequestAnimationFrame
) - Render sisi server (server-side rendering)
- Kesalahan yang dilemparkan di dalam Error Boundary itu sendiri (bukan di turunannya)
Strategi Penanganan Kesalahan Tingkat Lanjut
1. Mekanisme Coba Ulang (Retry)
Dalam beberapa kasus, mungkin dimungkinkan untuk pulih dari kesalahan dengan mencoba ulang operasi yang menyebabkannya. Misalnya, jika permintaan jaringan gagal, Anda dapat mencobanya lagi setelah jeda singkat. Error Boundaries dapat digabungkan dengan mekanisme coba ulang untuk memberikan pengalaman pengguna yang lebih tangguh.
// ErrorBoundaryWithRetry.js
import React from 'react';
class ErrorBoundaryWithRetry extends React.Component {
constructor(props) {
super(props);
this.state = {
hasError: false,
retryCount: 0,
};
}
static getDerivedStateFromError(error) {
return {
hasError: true,
};
}
componentDidCatch(error, errorInfo) {
console.error("Caught error: ", error, errorInfo);
}
handleRetry = () => {
this.setState(prevState => ({
hasError: false,
retryCount: prevState.retryCount + 1,
}), () => {
// Ini memaksa komponen untuk me-render ulang. Pertimbangkan pola yang lebih baik dengan props yang terkontrol.
this.forceUpdate(); // PERINGATAN: Gunakan dengan hati-hati
if (this.props.onRetry) {
this.props.onRetry();
}
});
};
render() {
if (this.state.hasError) {
return (
<div>
<h2>Terjadi kesalahan.</h2>
<button onClick={this.handleRetry}>Coba Lagi</button>
</div>
);
}
return this.props.children;
}
}
export default ErrorBoundaryWithRetry;
Komponen ErrorBoundaryWithRetry
menyertakan tombol coba ulang yang, saat diklik, mengatur ulang state hasError
dan me-render ulang komponen turunan. Anda juga dapat menambahkan retryCount
untuk membatasi jumlah percobaan ulang. Pendekatan ini bisa sangat berguna untuk menangani kesalahan sementara, seperti gangguan jaringan sementara. Pastikan prop `onRetry` ditangani dengan sesuai dan mengambil ulang/menjalankan ulang logika yang mungkin telah mengalami kesalahan.
2. Feature Flags
Feature flags memungkinkan Anda untuk mengaktifkan atau menonaktifkan fitur di aplikasi Anda secara dinamis, tanpa menerapkan kode baru. Error Boundaries dapat digunakan bersama dengan feature flags untuk menurunkan fungsionalitas secara anggun jika terjadi kesalahan. Misalnya, jika fitur tertentu menyebabkan kesalahan, Anda dapat menonaktifkannya menggunakan feature flag dan menampilkan pesan kepada pengguna yang menunjukkan bahwa fitur tersebut untuk sementara tidak tersedia.
3. Pola Circuit Breaker
Pola circuit breaker adalah pola desain perangkat lunak yang digunakan untuk mencegah aplikasi mencoba berulang kali menjalankan operasi yang kemungkinan besar akan gagal. Ini bekerja dengan memantau tingkat keberhasilan dan kegagalan suatu operasi dan, jika tingkat kegagalan melebihi ambang batas tertentu, "membuka sirkuit" dan mencegah upaya lebih lanjut untuk menjalankan operasi selama periode waktu tertentu. Ini dapat membantu mencegah kegagalan beruntun dan meningkatkan stabilitas aplikasi secara keseluruhan.
Error Boundaries dapat digunakan untuk mengimplementasikan pola circuit breaker dalam aplikasi React. Ketika Error Boundary menangkap kesalahan, ia dapat menambah penghitung kegagalan. Jika penghitung kegagalan melebihi ambang batas, Error Boundary dapat menampilkan pesan kepada pengguna yang menunjukkan bahwa fitur tersebut untuk sementara tidak tersedia dan mencegah upaya lebih lanjut untuk menjalankan operasi. Setelah periode waktu tertentu, Error Boundary dapat "menutup sirkuit" dan mengizinkan upaya untuk menjalankan operasi lagi.
Kesimpulan
React Error Boundaries adalah alat penting untuk membangun aplikasi yang kuat dan ramah pengguna. Dengan mengimplementasikan Error Boundaries, Anda dapat mencegah kesalahan merusak seluruh aplikasi Anda, menyediakan UI fallback yang anggun bagi pengguna Anda, dan mencatat kesalahan ke layanan pemantauan untuk debugging dan analisis. Dengan mengikuti praktik terbaik dan strategi tingkat lanjut yang diuraikan dalam panduan ini, Anda dapat membangun aplikasi React yang tangguh, andal, dan memberikan pengalaman pengguna yang positif, bahkan saat menghadapi kesalahan yang tidak terduga. Ingatlah untuk fokus pada penyediaan pesan kesalahan yang membantu dan dilokalkan untuk audiens global.